#ifndef __tenacitas_async__async__h__
#define __tenacitas_async__async__h__

// =============================================================================
/**
   @file 
   File description
*/


// =============================================================================
//                                 C++ Headers

#include <list>
#include <memory>

// =============================================================================
//                                 3rds Headers

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>


// =============================================================================
//                                 Our Headers


// =============================================================================
//                                 Namespaces
using namespace std;


// =============================================================================
//                                 Macro Contants

/**
 */


// =============================================================================
//                                 Macro Commands

/**
 */


/**
   namespace of the organization
*/
namespace tenacitas {
    /**
       namespace for the project
    */
    namespace async {

        // =========================== Typedefs ===========================
        /** */


        // ============================ Pre-Declarations ==================


        // ============================ Attributes ========================
        /** */


        // ============================ Functions =========================
        /** */


        // ============================ Classes ===========================

        /** List of unhandled events

            Simple implementation of the list of unhandled events
            @nosubgrouping 
        */
        template <typename t_logger, typename... t_event_args>
        class unhandled {

        public:

            // --- unhandled - Public Internal Types ------------------------

            /** Grouping the types of the arguments to the handler */
            typedef std::tuple<t_event_args...> event_args_tuple_t;

            /** Type of pointer to the grouping the types of the arguments to the handler */
            typedef typename std::shared_ptr<event_args_tuple_t> event_args_tuple_ptr_t;

            /** Type of logger */
            typedef t_logger logger_t;

            /** Type of pointer to the logger */
            typedef typename logger_t::ptr_t logger_ptr_t;

            // --- unhandled - Public Constructors --------------------------

            /** Consructor */
            unhandled( logger_ptr_t p_logger ) 
                : m_logger( p_logger ),
                  m_mutex( ),
                  m_list( ) {}

            /** Destructor */
            ~unhandled( ) {}

            // --- unhandled - Public Accessors -----------------------------

            /** Adds an event */
            void add( event_args_tuple_ptr_t p_event_params ) {
                boost::lock_guard<boost::mutex> l_lock( m_mutex );
                m_list.push_back( p_event_params );
            }

            /** Removes an event */
            event_args_tuple_ptr_t remove( ) {

                boost::lock_guard<boost::mutex> l_lock( m_mutex );

                // reference the event in the begining of the list
                event_args_tuple_ptr_t l_handler_parms = *( m_list.begin( ) );
	
                // remove the begining of the list
                m_list.erase( m_list.begin( ) );

                return l_handler_parms;
            }

            /** Indicates if there are no events waiting to be handled */
            bool empty( ) const { 
                return m_list.empty( );
            }

            /** Retrieves the size of list */
            size_t size( ) const {
                return static_cast<size_t>( m_list.size( ) );
            }

        private:

            // --- unhandled - Private Attributes ---------------------------

            /** Logger object */
            logger_ptr_t m_logger;

            /** Protects access to the list of unhandled events */
            boost::mutex m_mutex;

            /** List of unhandled events */
            std::list<event_args_tuple_ptr_t> m_list;
         
        };
    }
}

// =============================================================================
//                     I M P L E M E N T A T I O N
// =============================================================================

namespace ten_asy = tenacitas::async;


#endif
